package edu.northwestern.cbits.purple_robot_manager.probes.features;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.probes.Probe;
import edu.northwestern.cbits.purple_robot_manager.probes.builtin.ContinuousProbe;
import android.content.Context;
import android.os.Bundle;
public abstract class UnivariateContinuousProbeFeature extends ContinuousProbeFeature
{
protected static int BUFFER_SIZE = 1024;
protected float[] value = new float[BUFFER_SIZE];
protected double[] timestamp = new double[BUFFER_SIZE];
protected int index = 0;
private boolean _filled = false;
private long _lastCheck = 0;
private boolean _running = false;
protected abstract String valueKey();
protected void analyzeBuffers(final Context context)
{
final long now = System.currentTimeMillis();
if (now - this._lastCheck > 10000 && this._running == false)
{
this._lastCheck = now;
final UnivariateContinuousProbeFeature me = this;
Runnable r = new Runnable()
{
public void run()
{
me._running = true;
Bundle data = new Bundle();
data.putDouble(Probe.BUNDLE_TIMESTAMP, now / 1000);
data.putString(Probe.BUNDLE_PROBE, me.name(context));
double maxTime = Double.MIN_VALUE;
double minTime = Double.MAX_VALUE;
DescriptiveStatistics stats = new DescriptiveStatistics(XYZContinuousProbeFeature.BUFFER_SIZE);
for (int i = 0; i < UnivariateContinuousProbeFeature.BUFFER_SIZE; i++)
{
stats.addValue(me.value[i]);
if (me.timestamp[i] > maxTime)
maxTime = me.timestamp[i];
if (me.timestamp[i] < minTime)
minTime = me.timestamp[i];
}
data.putDouble("MIN", stats.getMin());
data.putDouble("MAX", stats.getMax());
data.putDouble("MEAN", stats.getMean());
data.putDouble("STD_DEV", stats.getStandardDeviation());
data.putDouble("RMS", Math.sqrt(stats.getSumsq() / UnivariateContinuousProbeFeature.BUFFER_SIZE));
data.putInt("BUFFER_SIZE", UnivariateContinuousProbeFeature.BUFFER_SIZE);
data.putDouble("FREQUENCY", ((double) UnivariateContinuousProbeFeature.BUFFER_SIZE)
/ ((maxTime - minTime) / 1000));
data.putDouble("DURATION", ((maxTime - minTime) / 1000.0));
me.transmitData(context, data);
me._running = false;
}
};
Thread t = new Thread(r);
t.start();
}
}
protected void processData(Context context, Bundle dataBundle)
{
String key = this.valueKey();
if (dataBundle.containsKey(key) && dataBundle.containsKey(ContinuousProbe.EVENT_TIMESTAMP))
{
double[] incomingTimes = dataBundle.getDoubleArray(ContinuousProbe.EVENT_TIMESTAMP);
float[] values = dataBundle.getFloatArray(key);
if (values != null)
{
for (int i = 0; i < incomingTimes.length; i++)
{
if (index + i > BUFFER_SIZE)
this._filled = true;
int bufferIndex = (index + i) % BUFFER_SIZE;
timestamp[bufferIndex] = incomingTimes[i];
value[bufferIndex] = values[i];
}
index += incomingTimes.length;
if (this._filled)
this.analyzeBuffers(context);
}
}
}
public String summarizeValue(Context context, Bundle bundle)
{
double mean = bundle.getDouble("MEAN");
double stdDev = bundle.getDouble("STD_DEV");
double rootMeanSquare = bundle.getDouble("RMS");
return String.format(context.getResources().getString(R.string.summary_univariate_statistics_feature), mean,
stdDev, rootMeanSquare);
}
}